package com.ttbj.waybill.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ttbj.core.util.DateUtils;
import com.ttbj.core.util.DtoTransitionUtils;
import com.ttbj.order.component.OrderCacheComponent;
import com.ttbj.product.api.DriverFacade;
import com.ttbj.product.api.LocationFacade;
import com.ttbj.product.api.OrderFacade;
import com.ttbj.product.api.OwnerFacade;
import com.ttbj.product.api.ReminderFacade;
import com.ttbj.product.bean.dto.DriverDto;
import com.ttbj.product.bean.dto.EntitieDto;
import com.ttbj.product.bean.dto.OrderDto;
import com.ttbj.product.bean.dto.OwnerDto;
import com.ttbj.product.bean.dto.WaybillDto;
import com.ttbj.product.bean.exception.BusinessException;
import com.ttbj.util.Assert;
import com.ttbj.waybill.dao.WaybillMapper;
import com.ttbj.waybill.po.Waybill;
import com.ttbj.waybill.service.DispachWaybillService;

@Service
public class DispachWaybillServiceImpl implements DispachWaybillService {

	private static final Logger logger = LoggerFactory.getLogger(DispachWaybillServiceImpl.class);

	@Autowired
	private WaybillMapper waybillMapper = null;

	@Autowired
	private DriverFacade driverFacade = null;

	@Autowired
	private OwnerFacade ownerFacade = null;

	@Autowired
	private LocationFacade locationFacade = null;

	@Autowired
	private OrderFacade orderFacade = null;
	
	@Autowired
	private ReminderFacade reminderFacade = null;

 

	private Long orderId = null;

	private String orderTruckType = null;

	private Integer orderDriverRequire = null;

	private Integer orderDriverAlready = null;

	private OrderDto orderDto = null;

	private OwnerDto reciver = null;

	private OwnerDto sender = null;
	


	@Override
	public Integer init(OrderDto orderDto) throws Exception {
		logger.info("自动派单开始");
		initOwner(orderDto);
		return initDriver(orderDto);

	}

	private Integer initDriver(OrderDto orderDto) throws Exception {
		this.orderId = orderDto.getOrderId();
		this.orderTruckType = orderDto.getOrderTruckType();
		this.orderDriverAlready = orderDto.getOrderDriverAlready();
		this.orderDto = orderDto;
		this.orderDriverRequire = orderDto.getOrderDriverRequire(); // 不能小于等于0
		logger.info("订单id:{},车辆类型:{},已派车辆:{},需求车辆:{}", orderId, orderTruckType, orderDriverAlready, orderDriverRequire);
		if (0 >= orderDriverRequire) {
			throw new BusinessException("订单包含需要司机数量不能小于等于0", 9999);
		}
		if(orderDriverAlready >=orderDriverRequire){
			throw new BusinessException("需要司机数不能小于已有司机数", 9999);
		}
		this.orderDriverRequire = orderDriverRequire - orderDriverAlready;
		logger.info("真正需求的车辆:{}", orderDriverRequire);
		List<DriverDto> list =  filterDriver(); // 出现三种情况 1.车辆够了 2.车辆一辆没有 3.车辆不够
		if (Assert.isEmpty(list)) {// 未匹配到车辆信息
			logger.info("未匹配到车辆信息");
			return 0;
		}
		int size = list.size();
		setOrder(size);//修改订单
		newWaybill(list);//生成运单
		dispatchRemind(list); //提醒司机接单
		if (size < orderDriverRequire) {// 未匹配到足够的车辆数量
			logger.info("未匹配到足够车辆数量");
			return 0;
		}
		return size;
	}
	
	
	
	/**
	 * 提醒司机由订单查收
	 * @param list
	 */
	private void dispatchRemind(List<DriverDto> list) {
		String reciverAddr = reciver.getOwnerAddr();
		String senderAddr = sender.getOwnerAddr();
		String senderPhone = sender.getOwnerPhone();
		reminderFacade.dispatchRemind(list,reciverAddr,senderAddr,senderPhone);
		
	}
	
	private String initOwner(OrderDto orderDto) throws Exception {
		Long orderSender = orderDto.getOrderSender();
		Long orderReciver = orderDto.getOrderReciver();
		reciver = ownerFacade.getOwner(null, orderReciver, 1);
		sender = ownerFacade.getOwner(null, orderSender, 0);
		return null;
	}

	/**
	 * 过滤司机
	 * 
	 * @param list
	 * @return
	 * @throws Exception
	 */
	private List<DriverDto> filterDriver() throws Exception {
		// 司机过滤
		// 司机是否已有此单信息 司机拒单数量大于3次 司机是否已有其他订单 司机是否允许接单
		List<EntitieDto> entityList = getEntityList();
		if (Assert.isEmpty(entityList)) {
			logger.info("鹰眼实体未获取到坐标附近的用户");
			return null;
		}
		List<DriverDto> driverList = getDriverList(entityList);
		logger.info("适配车型并过滤停止接单后的司机:{}" + driverList);
		if (Assert.isEmpty(driverList)) {
			logger.info("未适配到车型司机");
			return null;
		}
		List<DriverDto> collect = driverList.stream()// 开始过滤
				.filter(driver -> driver != null)// 司机信息非空
				.filter(driver -> null != driver.getDriverId())// 司机id验证
				.filter(driver -> null != driver.getDriverTruck() && -1l != driver.getDriverTruck())// 司机当前绑定了车辆
				.filter(driver -> isExamine(driver.getDriverToExamine()))// 司机通过验证
				.filter(driver -> isOrder(driver, orderId))// 司机是否已有此单信息
				.filter(dirver -> isWaybill(dirver.getDriverId()))// 司机当前无订单
				.filter(driver -> 3 > refuseNum(driver.getDriverId()))// 当天拒单3次
				.filter(driver -> 0 == driver.getDriverAllowWaybill())// 司机允许接单
				.collect(Collectors.toList());
		logger.info("最终车辆:{}" + collect);
		if (Assert.isEmpty(collect)) {
			return null;
		}
		/* 车辆数量处理 */
		int size = collect.size();
		if (size > orderDriverRequire) {// 大于需求车辆
			collect = collect.subList(0, orderDriverRequire);
		}
		return collect;
	}

	/**
	 * 生成货运单
	 * 
	 * @param query
	 * @param ready
	 * @param orderId
	 * @param list
	 * @throws Exception
	 */
	private void newWaybill(List<DriverDto> list) throws Exception {
		list.stream().forEach(driver -> waybillMapper.insertSelective(new Waybill(orderId, driver.getDriverId(), DateUtils.getCurDttStr(), driver.getTruck().getTruckCarnum())));
	}

	/**
	 * 设置订单
	 * 
	 * @param query
	 * @param ready
	 * @param orderId
	 * @throws Exception 
	 */
	private void setOrder(Integer size) throws Exception {
		// TODO Auto-generated method stub
		logger.info("修改订单状态");
		OrderDto order = orderDto;
		/* 生成货运单表 */
		order.setOrderDriverAlready(size + orderDriverAlready);
		/* 修改数据库车辆数目 */
		orderFacade.updateOrder(orderDto);
	}

	/**
	 * 司机是否已有此单信息(证明司机没有退过此单和此单的已有司机)
	 * 
	 * @param driver
	 * @param orderId
	 */
	private boolean isOrder(DriverDto driver, Long orderId) {
		WaybillDto waybill = queryWayBill(new WaybillDto(driver.getDriverId(), orderId));
		if (null == waybill) {
			return true;
		}
		return false;
	}

	/**
	 * 检查拒单
	 * 
	 * @param driverid
	 * @return
	 */
	private Integer refuseNum(Long driverid) {
		Integer stateNumDay = waybillMapper.stateNumDay(driverid, -1);
		if (null == stateNumDay) {
			stateNumDay = 0;
		}
		return stateNumDay;
	}

	/**
	 * 获取订单
	 * 
	 * @param waybillDto
	 * @return
	 */
	private WaybillDto queryWayBill(WaybillDto waybillDto) {
		if (null == waybillDto) {
			return null;
		}
		WaybillDto waybill = waybillMapper.getWayBill(waybillDto);
		if (null != waybill) {
			waybill = (WaybillDto) DtoTransitionUtils.trans(WaybillDto.class, waybill);
		}
		return waybill;
	}

	/**
	 * 司机当前是否有订单
	 * 
	 * @param driverId
	 * @return
	 */
	private boolean isWaybill(Long driverId) {
		Long currentId = waybillMapper.currentWaybill(driverId);
		if (null == currentId) {
			logger.info("司机id:{} 当前没有订单", driverId);
			return true;
		}
		return false;
	}

	
	private boolean isExamine(Integer examine) {
		if (null == examine) {
			logger.info("司机验证为null");
			return false;
		}
		return examine.equals(1);
	}

	/**
	 * 获取鹰眼实体
	 * 
	 * @return
	 * @throws Exception
	 */
	private List<EntitieDto> getEntityList() throws Exception {
		if (!Assert.assertNonNullField0(sender, "ownerLng", "ownerLat")) {
			logger.debug("搬出地或是寄件地坐标不能为空");
			throw new BusinessException("搬出地或是寄件地坐标不能为空", 9999);
		}
		String lng = sender.getOwnerLng();
		String lat = sender.getOwnerLat();
		if (!lng.contains(".") || !lat.contains(".")) {
			logger.debug("非法坐标");
			throw new BusinessException("非法坐标", 9999);
		}
		List<EntitieDto> entites = locationFacade.getEntites(lng, lat, orderDriverRequire);
		logger.info("鹰眼实体：{}", entites);
		return entites;
	}

	/**
	 * 适配车型用户
	 * 
	 * @param entites
	 * @return
	 * @throws Exception
	 */
	private List<DriverDto> getDriverList(List<EntitieDto> entites) throws Exception {
		/*车辆类型状态修改为字符串类型的数字*/
		List<DriverDto> list = driverFacade.matchEntityWithTruckType(Integer.valueOf(orderTruckType), entites);
		logger.info("司机信息集合:{}" + list);
		if (Assert.isEmpty(list)) {
			return list;
		}
		// 过滤掉已转手动单
		return list.stream().filter(driver -> 0 == driver.getDriverAllowWaybill()).collect(Collectors.toList());
	}

}
